﻿using System;
using System.Globalization;
using System.Windows.Forms;
using SoftwareConsulting.BI11.Studio.Core.DBProviders;
using SoftwareConsulting.BI11.Studio.Core.Project;
using SoftwareConsulting.BI11.Studio.Core.Project.Metadata;
using SoftwareConsulting.BI11.Studio.InternalServices;
using SoftwareConsulting.BI11.Studio.UI.Properties;

namespace SoftwareConsulting.BI11.Studio.UI.ProjectExplorer.Tables
{
    public partial class FieldPropertiesDialog : RestorableForm
    {
        private bool _programStateChange;
        private bool _isNewField;
        private ITable _Table;
        private string _FieldName;        
        private MainForm _MainForm;

        /// <summary>
        /// Возвращает текущий проект
        /// </summary>
        public ProjectDescriptor ProjectLink
        {
            get
            {
                return _MainForm.ProjectExplorer.ProjectLink;
            }
        }

        /// <summary>
        /// Конструктор
        /// </summary>      
        /// <param name="parTableID"></param>
        /// <param name="parFieldID"></param>
        public FieldPropertiesDialog(MainForm mainForm, bool newField, ITable parentTable, string parentFieldName)
        {
            _programStateChange = false;
            _MainForm = mainForm;
            _isNewField = newField;
            _Table = parentTable;
            _FieldName = parentFieldName;
            InitializeComponent();
        }

        private void btnCancel_Click(object sender, EventArgs e)
        {
            Close();
        }

        /// <summary>
        /// Инициализация диалога
        /// </summary>
        private void Initialize()
        {            
            if (_isNewField)
            {
                cboxFieldType.SelectedIndex = 0;
                FieldDateTimePicker.Value = DateTime.Now;
            }            
            else
            {
                DataColumnProperties dp = _Table.GetColumnProperties(_FieldName);
                // загружаем значения
                cboxAutoInc.Checked = dp.ToAutoInc;
                cboxUnique.Checked = dp.IsUniqueValue;                  
                tboxFieldCaption.Text = dp.Name;
                tboxSeed.Text = dp.AutoIncSeed.ToString(CultureInfo.CurrentCulture);
                tboxStep.Text = dp.AutoIncStep.ToString(CultureInfo.CurrentCulture);
                cboxFieldType.SelectedItem = dp.ColumnType.ToString();
                cboxFieldType.Enabled = false;
                DefaultCheck.Checked = (!(dp.DefaultValue is DBNull)) && (dp.DefaultValue != null);
                if (DefaultCheck.Checked)
                {
                    switch (dp.ColumnType.ToString())
                    {
                        case "System.String":
                            DefaultBox.Text = dp.DefaultValue.ToString();
                            break;
                        case "System.Boolean":
                            DefaultBool.Checked = (bool)dp.DefaultValue;
                            break;
                        case "System.Int32":
                            DefaultNumeric.Value = (int)dp.DefaultValue;
                            break;
                        case "System.Double":
                            DefaultBox.Text = dp.DefaultValue.ToString();
                            break;
                        case "System.DateTime":
                            FieldDateTimePicker.Value = (DateTime)dp.DefaultValue;
                            break;
                    }
                }
            }
            UpdateAbilities();
        }

        /// <summary>
        /// Применяет изменения и закрывает диалог
        /// </summary>
        private void ApplyAndClose()
        {
            //проверяем введенные данные
            int seed = 0, step = 1;
            // имя
            try
            {
                tboxFieldCaption.Text = GeneralMethods.TrimName(tboxFieldCaption.Text);
            }
            catch (BIIncorrectNameException ex)
            {
                GeneralMethods.ShowUserError(ex.Message);
                tboxFieldCaption.Focus();
                tboxFieldCaption.SelectAll();
                return;
            }
            // seed
            try
            {
                seed = Math.Abs(Convert.ToInt32(tboxSeed.Text, CultureInfo.CurrentCulture));
            }
            catch (FormatException)
            {
                GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_NAN);
                tboxSeed.Focus();
                return;
            }
            catch (OverflowException)
            {
                GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_NUMBEROUTOFRANGE);
                tboxSeed.Focus();
                return;
            }
            // step
            try
            {
                step = Math.Abs(Convert.ToInt32(tboxStep.Text, CultureInfo.CurrentCulture));
            }
            catch (FormatException)
            {
                GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_NAN);
                tboxStep.Focus();
                return;
            }
            catch (OverflowException)
            {
                GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_NUMBEROUTOFRANGE);
                tboxStep.Focus();
                return;
            }
            if (step == 0)
            {
                GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_ZERODENIED);
                tboxStep.Focus();                
                return;
            }                        
            //значение по умолчанию
            Type typ = System.Type.GetType(cboxFieldType.Text);            
            object defval = null;
            if (DefaultCheck.Checked)
            {                
                switch (typ.ToString())
                {
                    case "System.String":
                        defval = DefaultBox.Text;
                        break;
                    case "System.Int32":
                        defval = Convert.ToInt32(DefaultNumeric.Value);
                        break;
                    case "System.Boolean":
                        defval = DefaultBool.Checked;
                        break;
                    case "System.Double":
                        double d = double.MaxValue;
                        if (double.TryParse(DefaultBox.Text, out d))
                        {
                            defval = d;
                        }
                        else
                        {
                            GeneralMethods.ShowUserError(Resources.BI_PROJECTEXPLORER_TABLE_ERROR_NAN);
                            DefaultBox.Focus();
                            DefaultBox.SelectAll();
                            return;
                        }
                        break;
                    case "System.DateTime":
                        defval = FieldDateTimePicker.Value;                        
                        break;
                }
            }
            // Применяем изменения
            string newcolname = tboxFieldCaption.Text;
            DataColumnProperties dp = new DataColumnProperties();
            dp.Name = newcolname;
            dp.ColumnType = typ;
            dp.DefaultValue = defval;
            dp.IsUniqueValue = cboxUnique.Checked;
            dp.ToAutoInc = cboxAutoInc.Checked;
            dp.AutoIncSeed = seed;
            dp.AutoIncStep = step;
            _Table.UpdateOrAddColumn(_FieldName, dp, DefaultCheck.Checked);            
            ProjectLink.UpdateTableColumnName(_Table.Label, _FieldName, newcolname);
            Close();
        }

        /// <summary>
        /// Обновляет возможности по изменению свойств поля
        /// </summary>
        private void UpdateAbilities()
        {            
            tboxSeed.Enabled = cboxAutoInc.Checked;
            tboxStep.Enabled = cboxAutoInc.Checked;
            DefaultBox.Enabled = DefaultCheck.Checked;
            FieldDateTimePicker.Enabled = DefaultCheck.Checked;
            DefaultNumeric.Enabled = DefaultCheck.Checked;
            DefaultBool.Enabled = DefaultCheck.Checked;
            cboxAutoInc.Enabled = _isNewField;
            DefaultCheck.Enabled = cboxAutoInc.Enabled || DefaultCheck.Checked || !cboxAutoInc.Checked;
        }

        /// <summary>
        /// Обрабатывает смену типа поля
        /// </summary>
        private void ApplyTypeChange()
        {
            switch (cboxFieldType.Text)
            {
                case "System.String":
                    FieldDateTimePicker.Visible = false;
                    DefaultBox.Visible = true;
                    DefaultNumeric.Visible = false;
                    DefaultBool.Visible = false;
                    break;
                case "System.Boolean":
                    FieldDateTimePicker.Visible = false;
                    DefaultBox.Visible = false;
                    DefaultNumeric.Visible = false;
                    DefaultBool.Visible = true;
                    break;
                case "System.DateTime":
                    FieldDateTimePicker.Visible = true;
                    DefaultBox.Visible = false;
                    DefaultNumeric.Visible = false;
                    DefaultBool.Visible = false;
                    break;
                case "System.Int32":
                    FieldDateTimePicker.Visible = false;
                    DefaultBox.Visible = false;
                    DefaultNumeric.Visible = true;
                    DefaultBool.Visible = false;
                    break;
                case "System.Double":
                    FieldDateTimePicker.Visible = false;
                    DefaultBox.Visible = true;
                    DefaultNumeric.Visible = false;
                    DefaultBool.Visible = false;
                    break;
            }
        }

        /// <summary>
        /// Обработка смены состояния флажка использования автоинкремента
        /// </summary>
        private void AutoincrementStateChanged()
        {
            if (cboxAutoInc.Checked)
            {
                _programStateChange = true;
                DefaultCheck.Checked = false;
                _programStateChange = false;
            }
            UpdateAbilities();
        }

        /// <summary>
        /// Обработка смены состояния флажка использования дефолтного значения
        /// </summary>
        private void DefaultStateChanged()
        {
            if (DefaultCheck.Checked)
            {
                _programStateChange = true;
                cboxAutoInc.Checked = false;
                cboxUnique.Checked = false;
                _programStateChange = false;
            }
            UpdateAbilities();
        }

        /// <summary>
        /// Обработка смены состояния флажка уникальных значений
        /// </summary>
        private void UniqueStateChanged()
        {
            if (cboxUnique.Checked)
            {
                _programStateChange = true;
                DefaultCheck.Checked = false;
                _programStateChange = false;
            }
            UpdateAbilities();
        }

        private void btnOK_Click(object sender, EventArgs e)
        {
            ApplyAndClose();
        }

        private void NewFieldForm_Load(object sender, EventArgs e)
        {
            Initialize();
        }

        private void cboxAutoInc_CheckedChanged(object sender, EventArgs e)
        {
            if (!_programStateChange)
            {
                AutoincrementStateChanged();
            }
        }

        private void DefaultCheck_CheckedChanged(object sender, EventArgs e)
        {
            if (!_programStateChange)
            {
                DefaultStateChanged();
            }
        }

        private void cboxFieldType_SelectedIndexChanged(object sender, EventArgs e)
        {
            ApplyTypeChange();
        }

        private void cboxUnique_CheckedChanged(object sender, EventArgs e)
        {
            UniqueStateChanged();
        }
    }
}
